﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.UI.EM.Views.Interfaces;
using Common.Model;
using System.ComponentModel;
using Common.Services;
using System.Data.Objects.DataClasses;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Windows;

namespace Common.UI.EM.Views
{
    public class ListPresentationModel<S, E, C, EV> : IListPresentationModel<S, E, C, EV>, INotifyPropertyChanged
        where S : IGenericEntityManagerService<E, C, EV>, new()
        where E : EntityObject
        where C : CriteriaEntity
        where EV : ViewEntity
    {

        #region IListPresentationModel<S,E,C,EV> Members

        public event ViewCalledEventHandler ViewCalled;
        public event DeleteCalledEventHandler DeleteCalled;
        public event ModifyCalledEventHandler ModifyCalled;
        public event AddCalledEventHandler AddCalled;

        #endregion

        public virtual String DeleteLabel
        {
            get
            {
                return "Eliminar";
            }
        }

        public IListView View
        {
            get;
            set;
        }

        IGenericEntityManagerService<E, C, EV> _entityManager;
        public IGenericEntityManagerService<E, C, EV> EntityManager
        {
            get
            {
                if (_entityManager == null)
                {
                    _entityManager = new S();
                }
                return _entityManager;
            }
        }

        Object _list;
        public Object List
        {
            get
            {
                return _list;
            }
            set
            {
                _list = value;
                OnPropertyChanged("List");
            }
        }

        public DelegateCommand<Object> ViewCommand
        {
            get;
            set;
        }
        public DelegateCommand<Object> DeleteCommand
        {
            get;
            set;
        }
        public DelegateCommand<Object> ModifyCommand
        {
            get;
            set;
        }
        public DelegateCommand<Object> AddCommand
        {
            get;
            set;
        }

        public ListPresentationModel(IListView view)
        {
            this.View = view;
            this.View.Model = this;

            this.AddCommands();
        }
        
        private void AddCommands()
        {
            this.ViewCommand = new DelegateCommand<object>(ExecuteViewCommand, CanExecuteViewCommand);
            this.DeleteCommand = new DelegateCommand<object>(ExecuteDeleteCommand, CanExecuteDeleteCommand);
            this.ModifyCommand = new DelegateCommand<object>(ExecuteModifyCommand, CanExecuteModifyCommand);
            this.AddCommand = new DelegateCommand<object>(ExecuteAddCommand, CanExecuteAddCommand);
        }


        private void ExecuteViewCommand(Object arg)
        {
            if (this.ViewCalled != null && this.View.GetSelectedEntity() != null)
            {
                this.ViewCalled(this, new Microsoft.Practices.Composite.Events.DataEventArgs<ViewEntity>(this.View.GetSelectedEntity()));
            }
        }

        private Boolean CanExecuteViewCommand(Object arg)
        {
            return true;
        }


        private void ExecuteDeleteCommand(Object arg)
        {
            if (this.View.GetSelectedEntity() != null && this.ValidateOnDelete())
            {
                this.DeleteEntity();

                if (this.DeleteCalled != null)
                {
                    this.DeleteCalled(this, new Microsoft.Practices.Composite.Events.DataEventArgs<ViewEntity>(this.View.GetSelectedEntity()));
                }
            }
        }

        protected virtual bool ValidateOnDelete()
        {
            if (MessageBox.Show("¿Está seguro que desea eliminar permanentemente el registro?", "Confirmación", MessageBoxButton.YesNo) == MessageBoxResult.No)
            {
                return false;
            }
            return true;
        }

        protected virtual void DeleteEntity()
        {
            try
            {
                EntityManager.Delete(this.View.GetSelectedEntity());
            }
            catch (Exception ex)
            {
                if (ex.InnerException.Message.Contains("FK") && ex.InnerException.Message.Contains("DELETE"))
                {
                    MessageBox.Show("La entidad que está tratando de eliminar está relacionada con otras entidades. Elimine dichas relaciones y vuelva a intentarlo.");
                }
                else
                {
                    throw ex;
                }
            }
        }

        private Boolean CanExecuteDeleteCommand(Object arg)
        {
            return true;
        }


        private void ExecuteModifyCommand(Object arg)
        {
            if (this.ModifyCalled != null && this.View.GetSelectedEntity() != null)
            {
                this.ModifyCalled(this, new Microsoft.Practices.Composite.Events.DataEventArgs<ViewEntity>(this.View.GetSelectedEntity()));
            }
        }

        private Boolean CanExecuteModifyCommand(Object arg)
        {
            return true;
        }


        private void ExecuteAddCommand(Object arg)
        {
            if (this.AddCalled != null)
            {
                this.AddCalled(this, new EventArgs());
            }
        }

        private Boolean CanExecuteAddCommand(Object arg)
        {
            return true;
        }


        public void LoadList(C criteriaEntity)
        {
            List = EntityManager.Read(criteriaEntity);
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region IListPresentationModel<S,E,C,EV> Members

        public void AddColumnDefinition(String columnName, String header)
        {
           this.View.AddColumnDefinition(columnName, header);
        }

        #endregion
    }
}